package gov.nasa.anml;

import java.util.*;


import gov.nasa.anml.lifted.*;
import gov.nasa.anml.utility.*;

import static gov.nasa.anml.lifted.Time.*;


public class State extends LocalState implements Cloneable {
	
	 // either this way
	public Step step; // how we got generated
	public State parent; // from what
	
	public int bra; // where exactly in time; (Context).start gives the float
	// this gives before/at/after (latter two only used during advance-time)
	
	// or...
//	public Step[] plan; // accumulate the whole plan
//	// second way allows forgetting the closed list

	
	public void clear() {
		constants.clear();
		fluents.clear();
		functions.clear();
		contexts.clear();
		// unnecessary?
		contexts.put(-1,this);
		step = null;
		parent = null;
	}

	// not exactly a clone.  Really prepares a child.
	public State clone() {
		State c;
		try {
			c = (State) super.clone();
		} catch (CloneNotSupportedException e) {
			return null;
		}
		c.constants = (iHashMap<? extends SimpleObject<?>>) constants.clone();
		c.fluents = (iFluentHistoryMap) fluents.clone();
		c.functions = (iFunctionHistoryMap) functions.clone();
		c.contexts = (iHashMap<LocalState>) contexts.clone();
		c.contexts.put(-1,c);
		c.parent = this;
		
		return c;
	}


	public History<?> resolveFluent(int key) {
		return fluents.get(key);
	}

	public BindingHistoryMap<?> resolveFunction(int id) {
		return functions.get(id);
	}

	@Deprecated
	public History<? extends SimpleObject<?>> addFluent(int key) {
		History<? extends SimpleObject<?>> place = ((History<? extends SimpleObject<?>>)fluents.get(key));
		if (place == null) {
			place = new History<SimpleObject<Object>>();
			fluents.put(key,place);
		}
		return place;
	}

	public <T extends SimpleObject<? super T>> BindingHistoryMap<T> makeFunction(FluentFunction<T> f) {
		BindingHistoryMap<T> extension = new BindingHistoryMap<T>(); 
		functions.put(f.id,extension);
		return extension;
	}

	public int hashCode() {
		return fluents.hashCode() ^ functions.hashCode();
	}

	/**
	 * 
	 * @param <T>
	 * @param key
	 * @param value
	 * 
	 * @deprecated Use resolveFluent() to get the history, and manipulate
	 * the history manually
	 */
	public <T extends SimpleObject<T>> void setFluent(int key, T value) {
		History<T> place = ((History<T>)fluents.get(key));
		if (place == null) {
			place = new History<T>();
			place.value = value.clone();
			fluents.put(key,place);
		} else {
			place.value.assign(value);
		}
	}
	
	public <W extends SimpleObject<W>> void putFluents(iMap<History<W>> m) {
		fluents.putAll(m);
	}

	public SimpleObject<?> removeFluent(int key) {
		return fluents.remove(key).value;
	}

	public int size() {
		return fluents.size();
	}

	public String toString() {
		return fluents.toString();
	}
	
	public LocalState getLocalState(int contextID) {
		return contexts.get(contextID);
	}
	
	/*
	public SimpleFloat getStart(int contextID) {
		return contexts.get(contextID).start;
	}
	public SimpleFloat getEnd(int contextID) {
		return contexts.get(contextID).end;
	} */
	
}

